using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using PowerManage.API.Auth;
using PowerManage.EntityFrameworkCore;
using PowerManage.Entity;

namespace PowerManage.API.Extensions;

/// <summary>
/// 数据库相关扩展
/// </summary>
/// 如何写扩展方法？
/// 扩展方法必须定义在一个静态类中，并且方法本身也必须是静态的
/// 扩展方法的第一个参数必须是 this 关键字修饰的，表示该方法将扩展哪个类型的实例。
///
/// 控制器分别注入不同的数据库操作对象，如何保证他们数据库上下文是同一个？
/// contextLifetime的作用就是：配置容器中注册DbContext服务的生存期
/// 默认是ServiceLifetime.Scoped，这样才能保证一次Http请求中，所有数据库上下文是同一个实例，这样才能保证事务是有效的。
/// 如果配置为ServiceLifetime.Transient，事务就会无效
public static class DbContextExtension
{
    /// <summary>
    /// 数据库上下文注入
    /// </summary>
    /// <param name="builder"></param>
    public static void AddPowerManageDbContext(this WebApplicationBuilder builder)
    {
        //数据库上下文注入
        builder.Services.AddDbContext<ApplicationDbContext>(options =>
        {
            //启用的数据库类型
            var provider = builder.Configuration.GetValue<string>(AppSettings.DataProvider);
            switch (provider)
            {
                case "PgSql":
                    var pgSqlConnectionString =
                        builder.Configuration.GetConnectionString(AppSettings.PgSqlConnection) ??
                        throw new InvalidOperationException(
                            "PgSqlConnection在appsettings.json中 not found");
                    options.UseNpgsql(pgSqlConnectionString);
                    break;
                case "Mysql":
                    var mySqlConnectionString =
                        builder.Configuration.GetConnectionString(AppSettings.MySqlConnection) ??
                        throw new InvalidOperationException(
                            "MysqlConnection在appsettings.json中 not found");
                    //MySql需要传入版本，ServerVersion.AutoDetect根据连接字符串自动获取
                    options.UseMySql(mySqlConnectionString, ServerVersion.AutoDetect(mySqlConnectionString));
                    break;
            }

            options.LogTo(Console.WriteLine); //打印sql日志，方便调试
        });

//Identity注入，添加数据库上下文 配置认证，授权 里面存储用户和角色数据  AddDefaultTokenProviders()：添加默认的令牌提供者
// builder.Services.AddIdentity<IdentityUser, IdentityRole>()
//     .AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
//这里是为了自定义Identity表名称 功能和上述注释的一样
        builder.Services.AddIdentity<EleUser, EleRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
    }
}